/**
* \file		Carte.h
* \brief	Création et gestion de Cartes, structure comprenant notamment
*		un tableau de cases
* \details	C'est ici que sont définis les accesseurs et mutateurs des
*		Cartes.
*/

#ifndef CARTE_H
#define CARTE_H
#include "Case.h"

/**
* \brief	Informations concernant un ensemble de cases
* \details	Cette structure contient un tableau de cases et les
*		différentes mesures de taille (x,y,z) de ce tableau.
*/

typedef struct
{
   Case ***tab;		/*!<Tableau de cases : tableau à 3 dimensions */
   unsigned int x;	/*!<Entier non signé : taille x du tableau */
   unsigned int y;	/*!<Entier non signé : taille y du tableau */
   unsigned int z;	/*!<Entier non signé : taille z du tableau */
} Carte;

/*========================== Gestion de la mémoire ==========================*/
/**
* \brief	Initialise le contenu d'une Carte donnée
* \details	Alloue de la mémoire au tableau de cases, met tous les
*		terrains de la surface 1 (z=0) sur terreSurf et tous les
*		terrains des autres surfaces sur terreSout.
* \param	pcarte		Pointeur sur une carte donnée
* \param	ptableauTerr	Tableau des terrains possibles et leur nombre
*/
void initCarte(Carte *pcarte, TabTerrains *ptableauTerr);

/**
* \brief	Crée une Carte
* \details	Crée une carte, alloue de la mémoire dans le tas pour la
*		stocker et l'initialise via initCarte
* \param	pcarte		Pointeur sur adresse d'une carte donnée
* \param	x		Entier non signé, taille x de la carte
* \param	y		Entier non signé, taille y de la carte
* \param	z		Entier non signé, taille z de la carte
* \param	ptableauTerr	Tableau des terrains possibles et leur nombre
*/
void creerCarte(Carte **pcarte, unsigned int x, unsigned int y, unsigned int z, TabTerrains *ptableauTerr);

/**
* \brief	Libère une Carte
* \details	Désalloue la mémoire originellement réservée pour le tableau
*		de cases de la carte et met à 0 toutes ses dimensions
* \param	pcarte		Carte à libérer
*/
void libereCarte(Carte *pcarte);

/**
* \brief	Détruit une Carte
* \details	Désalloue la mémoire originellement réservée à la carte et
*		passe à NULL son pointeur 
* \param	pcarte		Carte à libérer
*/
void detruireCarte(Carte *pcarte);


/*==============================Accesseurs===============================*/
/**
* \brief	Retourne la taille x de la carte
* \param	pcase		Pointeur sur la Carte
* \return	Un entier non signé
*/
unsigned int getXCarte(const Carte *pcarte);

/**
* \brief	Retourne la taille y de la carte
* \param	pcase		Pointeur sur la Carte
* \return	Un entier non signé
*/
unsigned int getYCarte(const Carte *pcarte);

/**
* \brief	Retourne la taille z de la carte
* \param	pcase		Pointeur sur la Carte
* \return	Un entier non signé
*/
unsigned int getZCarte(const Carte *pcarte);

/**
* \brief	Retourne la Case dont les coordonnées ont été passées
* \param	pcase		Pointeur sur la Carte
* \param	coordX		Entier non signé, coordonnée x de la case
* \param	coordY		Entier non signé, coordonnée y de la case
* \param	coordZ		Entier non signé, coordonnée z de la case
* \return	Un pointeur sur la Case dont on a fourni les coordonnées
*/
Case *getCaseCarte(const Carte *pcarte, unsigned int coordX, unsigned int coordY, unsigned int coordZ);

/**
* \brief	Retourne un tableau des pointeurs sur les cases adjacentes à
*		celle dont on aura passé les coordonnées
* \param	pcase		Pointeur sur la Carte
* \param	coordX		Entier non signé, coordonnée x de la case
* \param	coordY		Entier non signé, coordonnée y de la case
* \param	coordZ		Entier non signé, coordonnée z de la case
* \return	Un pointeur sur le tableau de pointeurs sur les cases
*		adjacentes de la case dont on aura passé les coordonnées
*/
Case **getCasesAdjacentesCarte(const Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ);

/**
* \brief	Renvoie le terrain d'une case de la carte dont on aura donné
*		les coordonnées.
* \param	pcarte		Pointeur sur une carte
* \param	coordX		Entier non signé, nouvelle valeur de X
* \param	coordY		Entier non signé, nouvelle valeur de Y
* \param	coordZ		Entier non signé, nouvelle valeur de Z
* \return	Un pointeur sur le Terrain de la case de coordonnées données
*/
Terrain *getTerrainCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ);

/**
* \brief	Retourne un pointeur sur la Production d'une case
*		dont on aura passé les coordonnées. Si pas de production,
*		retourne NULL
* \param	pcase		Pointeur sur la Carte
* \param	coordX		Entier non signé, coordonnée x de la case
* \param	coordY		Entier non signé, coordonnée y de la case
* \param	coordZ		Entier non signé, coordonnée z de la case
* \return	Un pointeur sur Production
*/
Production *getProdCaseCarte(const Carte *pcarte, const unsigned int coordX, const unsigned int coordY, const unsigned int coordZ);

/**
* \brief	Retourne le nom de la production d'une case dont on aura passé
*		les coordonnées. Si pas de production, retourne NULL
* \param	pcase		Pointeur sur la Carte
* \param	coordX		Entier non signé, coordonnée x de la case
* \param	coordY		Entier non signé, coordonnée y de la case
* \param	coordZ		Entier non signé, coordonnée z de la case
* \return	Une chaîne de caractères
*/
char *getNomProdCaseCarte(const Carte *pcarte, const unsigned int coordX, const unsigned int coordY, const unsigned int coordZ);

/**
* \brief	Retourne la valeur de Pourcentage de la production d'une case
*		dont on aura passé les coordonnées. Si pas de production,
*		retourne -1
* \param	pcase		Pointeur sur la Carte
* \param	coordX		Entier non signé, coordonnée x de la case
* \param	coordY		Entier non signé, coordonnée y de la case
* \param	coordZ		Entier non signé, coordonnée z de la case
* \return	Un entier
*/
int getPourcentageProdCaseCarte(const Carte *pcarte, const unsigned int coordX, const unsigned int coordY, const unsigned int coordZ);

/**
* \brief	Retourne la valeur de Vitesse de la production d'une case
*		dont on aura passé les coordonnées. Si pas de production,
*		retourne -1
* \param	pcase		Pointeur sur la Carte
* \param	coordX		Entier non signé, coordonnée x de la case
* \param	coordY		Entier non signé, coordonnée y de la case
* \param	coordZ		Entier non signé, coordonnée z de la case
* \return	Un entier
*/
int getVitesseProdCaseCarte(const Carte *pcarte, const unsigned int coordX, const unsigned int coordY, const unsigned int coordZ);

/*============================== Mutateurs ==============================*/
/**
* \brief	Remplace la valeur de la taille X de la carte par une
*		nouvelle valeur, et réalloue la mémoire pour cette nouvelle
*		valeur.
* \param	pcarte		Pointeur sur une carte
* \param	nouvX		Entier non signé, nouvelle valeur de X
*/
void setXCarte(Carte *pcarte, unsigned int nouvX);

/**
* \brief	Remplace la valeur de la taille Y de la carte par une
*		nouvelle valeur, et réalloue la mémoire pour cette nouvelle
*		valeur.
* \param	pcarte		Pointeur sur une carte
* \param	nouvY		Entier non signé, nouvelle valeur de Y
*/
void setYCarte(Carte *pcarte, unsigned int nouvY);

/**
* \brief	Remplace la valeur de la taille Z de la carte par une
*		nouvelle valeur, et réalloue la mémoire pour cette nouvelle
*		valeur.
* \param	pcarte		Pointeur sur une carte
* \param	nouvZ		Entier non signé, nouvelle valeur de Z
*/
void setZCarte(Carte *pcarte, unsigned int nouvZ);

/**
* \brief	Remplace la case dont les coordonnées ont été passées en
*		paramètres par une case donnée
* \param	pcarte		Pointeur sur une carte
* \param	coordX		Entier non signé, nouvelle valeur de X
* \param	coordY		Entier non signé, nouvelle valeur de Y
* \param	coordZ		Entier non signé, nouvelle valeur de Z
* \param	nouvCase	Case, case de remplacement
*/
void setCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, Case *nouvCase);

/**
* \brief	Remplace le terrain de la case dont les coordonnées ont été
*		passées en paramètres par un terrain donné
* \param	pcarte		Pointeur sur une carte
* \param	coordX		Entier non signé, nouvelle valeur de X
* \param	coordY		Entier non signé, nouvelle valeur de Y
* \param	coordZ		Entier non signé, nouvelle valeur de Z
* \param	pnouvTerrain	Terrain à assigner à la case
*/
void setTerrainCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, Terrain *pnouvTerrain);

/**
* \brief	Attribue une production à une case dont on aura passé les
*		coordonnées
* \details	Si la case a déjà une production, libère la production
*		initialement présente puis attribue la nouvelle (en terme de
*		jeu : la construction d'un bâtiment sur une ressource entraîne
*		la destruction de la ressource).
* \param	pcarte		Pointeur sur une carte
* \param	coordX		Entier non signé, nouvelle valeur de X
* \param	coordY		Entier non signé, nouvelle valeur de Y
* \param	coordZ		Entier non signé, nouvelle valeur de Z
* \param	nomProd		Nom de  la production à assigner
*/
void setNouvProdCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, char *nomProd);

/**
* \brief	Remplace le pourcentage de production de la case par une
*		valeur donnée additionnée à la valeur de base, si la case
*		dont on aura passé les coordonnées a bien une production
* \param	pcarte		Pointeur sur une carte
* \param	coordX		Entier non signé, nouvelle valeur de X
* \param	coordY		Entier non signé, nouvelle valeur de Y
* \param	coordZ		Entier non signé, nouvelle valeur de Z
* \param	pourcent	Nouvelle valeur à assigner
*/
void ajoutePourcentageProdCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, int pourcent);

/**
* \brief	Remplace la vitesse de production de la case par une
*		valeur donnée additionnée à la valeur de base, si la case
*		dont on aura passé les coordonnées a bien une production
* \param	pcarte		Pointeur sur une carte
* \param	coordX		Entier non signé, nouvelle valeur de X
* \param	coordY		Entier non signé, nouvelle valeur de Y
* \param	coordZ		Entier non signé, nouvelle valeur de Z
* \param	vitesse		Nouvelle valeur à assigner
*/
void ajouteVitesseProdCaseCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, int vitesse);

/*===============================Manipulation================================*/

/**
* \brief	Pour une case donnée, remplit son tableau de cases adjacentes
*		et son nombre de cases adjacentes.
* \param	pcarte		Pointeur sur une carte
* \param	coordX		Entier non signé, nouvelle valeur de X
* \param	coordY		Entier non signé, nouvelle valeur de Y
* \param	coordZ		Entier non signé, nouvelle valeur de Z
* \param	ptableauTerr	Tableau des terrains possibles et leur nombre
*/
void setCasesAdjacentesCarte(Carte *pcarte, unsigned int coordX, unsigned int coordY,unsigned int coordZ, const TabTerrains *ptableauTerr);

/**
* \brief	Plante un nombre donné de graines pour la génération de
*		groupes d'un type de terrain donné et les fait pousser
* \param	pcarte		Pointeur sur une carte
* \param	nbGraines	Entier non signé, nombre de graines
* \param	z		Entier non signé, strate de la carte à traiter
* \param	pnouvTerrain	Pointeur sur terrain à assigner 
* \param	tailleMax	Taille maximale d'une tache issue d'une graine
*/
void planterGrainesCarte(Carte *pcarte, unsigned int nbGraines, unsigned int z, Terrain *pnouvTerrain, unsigned int tailleMax);

/**
* \brief	si x et/ou y dépasse(nt) d'une valeur maximale, les ajuste à
*		cette valeur.
* \param	x		Pointeur sur la coordonnée x à ajuster
* \param	y		Pointeur sur la coordonnée y à ajuster
* \param	xMax		Valeur maximale pour x
* \param	yMax		Valeur maximale pour y
*/
void ajusteCoordCarte(unsigned int *x, unsigned int *y, unsigned int xMax, unsigned int yMax);

/**
* \brief	"Fait pousser" une graine d'un type de terrain et de
*		coordonnées donnés : modifie les terrains alentours suivant un
*		parcours en spirale.
* \param	pcarte		Pointeur sur une carte
* \param	xDep		Coordonnée x de départ
* \param	yDep		Coordonnée y de départ
* \param	z		Entier non signé, strate de la carte à traiter
* \param	nbMax		Nombre maximal de cases à modifier (en gros :
*				taille maximale de la forme générée)
* \param	terrGraine	Pointeur sur le terrain à assigner 
*/
void pousseGraineCarte(Carte *pcarte, unsigned int xDep, unsigned int yDep, unsigned int z, unsigned int nbMax, Terrain *terrGraine);

/**
* \brief	Renvoie 1 si la case est adjacente à une case étant d'un
*		terrain donné. Sinon, renvoie 0.
* \param	pcarte		Pointeur sur une carte
* \param	x		Entier non signé, coordonnée x de la case
* \param	y		Entier non signé, coordonnée y de la case
* \param	z		Entier non signé, coordonnée z de la case
* \param	nomTerrain	Chaîne de caractères, nom du terrain
* \param	ptableauTerr	Pointeur sur le tableau de terrains utilisé
* \return	Un caractère
*/
char caseVoisineDeTerrainCarte(Carte *pcarte, unsigned int x, unsigned int y,unsigned int z, char *nomTerrain, const TabTerrains *ptableauTerr);

/**
* \brief	Met du sable autour des lacs de la surface de la carte
* \param	pcarte		Pointeur sur une carte
* \param	ptableauTerr	Pointeur sur le tableau de terrains utilisé
*/
void sableCarte(Carte *pcarte, TabTerrains *ptableauTerr);

/**
* \brief	"Fait pousser" une graine d'un type de production et de
*		coordonnées donnés : modifie les cases alentours suivant un
*		parcours en spirale.
* \param	pcarte		Pointeur sur une carte
* \param	xDep		Coordonnée x de départ
* \param	yDep		Coordonnée y de départ
* \param	z		Entier non signé, strate de la carte à traiter
* \param	nbMax		Nombre maximal de cases à modifier (en gros :
*				taille maximale de la forme générée)
* \param	nomProdGraine	Chaîne de caractères, nom de la production
* \param	nomTerrainTabou	Chaîne de caractères, nom du terrain sur
*				lequel la production ne peut exister (à
*				transformer en tableau de chaines si jamais on
*				étoffe au point d'avoir plusieurs terrains
*				incompatibles avec une prod)
*/
void pousseGraineProdCarte(Carte *pcarte, unsigned int xDep, unsigned int yDep, unsigned int z, unsigned int nbMax, char *nomProdGraine, char *nomTerrainTabou);

/**
* \brief	Plante un nombre donné de graines pour la génération de
*		groupes d'un type de production donné et les fait pousser
* \param	pcarte		Pointeur sur une carte
* \param	nbGraines	Entier non signé, nombre de graines
* \param	z		Entier non signé, strate de la carte à traiter
* \param	nomProdGraine	Chaîne de caractères, nom de la production
* \param	tailleMax	Taille maximale d'une tache issue d'une graine
* \param	nomTerrainTabou	Chaîne de caractères, nom du terrain sur
*				lequel la production ne peut exister (à
*				transformer en tableau de chaines si jamais on
*				étoffe au point d'avoir plusieurs terrains
*				incompatibles avec une prod)
*/
void planterGrainesProdCarte(Carte *pcarte, unsigned int nbGraines, unsigned int z, char *nomNouvProd, unsigned int tailleMax, char *nomTerrainTabou);

/**
* \brief	Crée et génère une carte à partir d'un tableau de terrains
* \param	ptableauTerr	Pointeur sur le tableau de terrains utilisé
* \param	x		Entier non signé, taille x de la carte
* \param	y		Entier non signé, taille y de la carte
* \param	z		Entier non signé, taille z de la carte
* \param	nbLacs		Entier non signé, nombre de lacs à placer
* \param	nbGrottes	Entier non signé, nombre de grottes à placer
* \param	nbForets	Entier non signé, nombre de forêts à placer
* \param	nbFilonsParStrate	Entier non signé, nombre de filons à
*					placer par strate de sous-sol
* \return	resCarte	Une carte générée aléatoirement
*/
Carte *genererCarte(unsigned int x, unsigned int y, unsigned int z, unsigned int nbLacs, unsigned int nbGrottes, unsigned int nbForets, unsigned int nbFilonsParStrate, TabTerrains *ptableauTerr);

/*================================== Test ===================================*/

/**
* \brief	Teste les différentes fonctions du module Carte
*/
void testCarte();

#endif
